import Koa from 'koa'
import { WX } from '..';
import { Plugin } from '../lib/Plugin'
import { isXML, toJSON, toXML } from '../tool/parser'

import { Request } from '../lib/wxRequest'
import { Reply } from '../lib/wxReply'
import { Store } from '../lib/Store';
import { echo } from '../tool/echo';


export default (wx: WX) => async function (ctx: Koa.ParameterizedContext<Koa.DefaultState, Koa.DefaultContext, any>, next: Function) {
    // 只处理 XML 类型
    if (isXML(ctx.request.body)) {

        /**
         * 在所有插件外创建对象比在插件内创建对象可能好一些。
         */

        const req = new Request(ctx.request.body);// 创建请求对象
        const reply = new Reply(req.data.ToUserName, req.data.FromUserName); // 创建回复对象
        const store = new Store(req.data.FromUserName);// 基于发送方创建的一个仓库
        // 遍历所有的插件，并创建它们
        for (const plugin of wx.plugins) {
            const _plugin: Plugin = new plugin(wx, req, reply, store);

            // 1.确认插件开启            
            if (plugin.disable) { continue }

            // 2.确认插件处理这次请求
            if (!_plugin.test()) { continue }

            try {
                // 3.开始处理
                ctx.body = await _plugin.process();// 等待处理结果(可能是异步函数)
            } catch (e) {
                echo(`插件 [${plugin.name}] 抛出未处理异常`, e as string)
            }


            // 4.确认被处理，则后续插件不在被执行
            if (!!ctx.body) {
                // 如果插件响应了字符串，则将其当作 文本 类型响应
                if (typeof ctx.body == 'string') {
                    ctx.body = reply.text(ctx.body);
                }
                if (typeof ctx.body == 'object') {
                    ctx.body = toXML(ctx.body)
                } else {
                    continue;
                }
                break;
            }
        }

        // 没有插件处理时，默认回复的内容
        if (!ctx.body) {
            ctx.body = wx.option.defaultContent
        } else {
            ctx.response.type = 'text/xml'
        }
        ctx.response.status = 200;
    } else {
        await next();
    }
    return Promise.resolve()
}